package org.gianrishandy.IEEE;

/**
 * @author Gian Rishandy
 */
public class IEEEFloatingPoint {
	private Double N;
	private int A;
	private Double B;
	private int exponent;
	private String binaryExponent;
	private int mantissa;
	private String binaryMantissa;
	private String sign;
	private String binaryIEEE;
	private String binaryByte0;
	private String binaryByte1;
	private String binaryByte2;
	private String binaryByte3;
	private String hexByte0;
	private String hexByte1;
	private String hexByte2;
	private String hexByte3;
	private String packedFormat;
	
	
	/**
	 * @param n (n ranges around 0>=n<1)
	 */
	public IEEEFloatingPoint(Double n) {
		this.sign = "0";
		this.N = n;
		bind();
	}
	
	
	/**
	 * Generate IEEE Floating Point
	 * But Set N First
	 */
	public void bind(){
		this.A = calculateA(N);
		this.B = calculateB(N, A);
		this.exponent = calculateExponent(A);
		this.binaryExponent = calculateBinaryExponent(exponent);
		this.mantissa = calculateMantissa(B);
		this.binaryMantissa = calculateBinaryMantissa(mantissa);
		this.binaryIEEE = this.sign + this.binaryExponent + this.binaryMantissa;
		this.binaryByte0 = this.binaryIEEE.substring(0, 8);
		this.binaryByte1 = this.binaryIEEE.substring(8, 16);
		this.binaryByte2 = this.binaryIEEE.substring(16, 24);
		this.binaryByte3 = this.binaryIEEE.substring(24, 32);
		this.hexByte0 = Integer.toHexString(Convert.binaryToInt(this.binaryByte0)).toUpperCase();
		this.hexByte1 = Integer.toHexString(Convert.binaryToInt(this.binaryByte1)).toUpperCase();
		this.hexByte2 = Integer.toHexString(Convert.binaryToInt(this.binaryByte2)).toUpperCase();
		this.hexByte3 = Integer.toHexString(Convert.binaryToInt(this.binaryByte3)).toUpperCase();
		this.packedFormat = calculatePackedFormat();
	}
	
	private int calculateA(Double d){
		int n = 0;
		Double r = 0.5;
		n = -1;
		
		for(int i=-2;r>d;i--){
			r = r / 2.00;
			n = i;
		}
		
		return n;
	}
	
	private Double calculateB(Double d, int n){
		double r = 1;
		int i = -1;
		
		while(i != n){
			r = r / 2;
			i--;
		}
		
		return ((2 * d )/r)-1;
	}
	
	private int calculateExponent(int a){
		return a + 127;
	}
	
	private int calculateMantissa(Double b){
		int l = 1;
		for(int i=1;i<24;i++){
			l = l * 2;
		}
		Double h = b * l;
		return h.intValue();
	}
	
	private String calculateBinaryExponent(int exponent){
		String binary = Integer.toBinaryString(exponent);
		if(binary.length()<8){
			int l = 8 - binary.length();
			for(int i=0;i<l;i++){
				binary = "0" + binary;
			}
		}
		return binary;
	}
	
	private String calculateBinaryMantissa(int mantissa){
		String binary = Integer.toBinaryString(mantissa);
		if(binary.length() < 24){
			int l = 24 - binary.length();
			for(int i=0;i<l;i++){
				binary = "0" + binary;
			}
		}
		return binary;
	}
	
	private String calculatePackedFormat(){
		String packedFormat = this.hexByte3 + this.hexByte2 + this.hexByte1 + this.hexByte0;
		if(packedFormat.length() < 8){
			int l = 8 - packedFormat.length();
			for(int i=0;i<l;i++){
				packedFormat = "0" + packedFormat;
			}
		}
		return packedFormat;
	}
	
	public Double getN() {
		return N;
	}
	public void setN(Double n) {
		N = n;
	}
	public int getA() {
		return A;
	}
	public void setA(int a) {
		A = a;
	}
	public Double getB() {
		return B;
	}
	public void setB(Double b) {
		B = b;
	}
	public int getExponent() {
		return exponent;
	}
	public void setExponent(int exponent) {
		this.exponent = exponent;
	}
	public String getBinaryExponent() {
		return binaryExponent;
	}
	public void setBinaryExponent(String binaryExponent) {
		this.binaryExponent = binaryExponent;
	}
	public int getMantissa() {
		return mantissa;
	}
	public void setMantissa(int mantissa) {
		this.mantissa = mantissa;
	}
	public String getBinaryMantissa() {
		return binaryMantissa;
	}
	public void setBinaryMantissa(String binaryMantissa) {
		this.binaryMantissa = binaryMantissa;
	}
	public String getSign() {
		return sign;
	}
	public void setSign(String sign) {
		this.sign = sign;
	}
	public String getBinaryByte0() {
		return binaryByte0;
	}
	public void setBinaryByte0(String binaryByte0) {
		this.binaryByte0 = binaryByte0;
	}
	public String getBinaryByte1() {
		return binaryByte1;
	}
	public void setBinaryByte1(String binaryByte1) {
		this.binaryByte1 = binaryByte1;
	}
	public String getBinaryByte2() {
		return binaryByte2;
	}
	public void setBinaryByte2(String binaryByte2) {
		this.binaryByte2 = binaryByte2;
	}
	public String getBinaryByte3() {
		return binaryByte3;
	}
	public void setBinaryByte3(String binaryByte3) {
		this.binaryByte3 = binaryByte3;
	}
	public String getBinaryIEEE() {
		return binaryIEEE;
	}
	public void setBinaryIEEE(String binaryIEEE) {
		this.binaryIEEE = binaryIEEE;
	}
	public String getHexByte0() {
		return hexByte0;
	}
	public void setHexByte0(String hexByte0) {
		this.hexByte0 = hexByte0;
	}
	public String getHexByte1() {
		return hexByte1;
	}
	public void setHexByte1(String hexByte1) {
		this.hexByte1 = hexByte1;
	}
	public String getHexByte2() {
		return hexByte2;
	}
	public void setHexByte2(String hexByte2) {
		this.hexByte2 = hexByte2;
	}
	public String getHexByte3() {
		return hexByte3;
	}
	public void setHexByte3(String hexByte3) {
		this.hexByte3 = hexByte3;
	}
	public String getPackedFormat() {
		return packedFormat;
	}
	public void setPackedFormat(String packedFormat) {
		this.packedFormat = packedFormat;
	}
}